home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SuperHack
/
SuperHack CD.bin
/
Hack
/
UNIX
/
TCPMON.ZIP
/
TCPMON.C
Wrap
C/C++ Source or Header
|
1996-06-10
|
10KB
|
450 lines
/*
* TCP Monitor (tcpmon) V1.0
*
* cc tcpmon.c -o tcpmon -lresolv
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/stropts.h>
#include <sys/signal.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/nit_if.h>
#include <net/nit_buf.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h>
#include <netinet/in_systm.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#define NIT_DEV "/dev/nit"
#define CHUNKSIZE 4096
#define STREAM_NULL (0)
#define STREAM_STOD (1)
#define STREAM_DTOS (2)
#define STREAM_MAX (3)
#define ISeq(s,d) ((s) == (d))
#define ISneq(s,d) ((s) != (d))
char *malloc (), *translate_host (), *device, *ProgName;
int debug, translate;
int if_fd = -1;
int Packet[CHUNKSIZE + 32], TCPport[10];
void
Pexit (err, msg)
int err;
char *msg;
{
perror (msg);
exit (err);
}
void
Zexit (err, msg)
int err;
char *msg;
{
fprintf (stderr, msg);
exit (err);
}
#define DEBUGstk(Msg,Num,Seq) \
if(debug) { \
printf(Msg,Num,Seq); fflush(stdout); \
}
#define IP ((struct ip *)Packet)
#define IP_OFFSET (0x1FFF)
#define SZETH (sizeof(struct ether_header))
#define IPLEN (ntohs(ip->ip_len))
#define IPHLEN (ip->ip_hl)
#define ADneq(s,t) ((s).s_addr != (t).s_addr)
/*
* important part of the prog, determines if a packet is one we want, and
* performs sycnhing of sequence numbers
*/
void
filter (cp, pktlen)
char *cp;
u_int pktlen;
{
int match = 0, i;
char *src, *dst, sp[15], dp[15];
register int Stream = STREAM_NULL;
register struct ip *ip;
struct in_addr Sipaddr;
struct in_addr Dipaddr;
struct servent *sv;
register struct tcphdr *tcph;
register u_long CurSEQ;
register u_char *p;
register u_short EtherType = ntohs (((struct ether_header *) cp)->ether_type);
if (EtherType < 0x600)
{
EtherType = *(u_short *) (cp + SZETH + 6);
cp += 8;
pktlen -= 8;
if (ISneq (EtherType, ETHERTYPE_IP))
return;
}
/* ugh, gotta do an alignment :-( */
bcopy (cp + SZETH, (char *) Packet, (int) (pktlen - SZETH));
ip = (struct ip *) Packet;
if (ISneq (ip->ip_p, IPPROTO_TCP))
return;
tcph = (struct tcphdr *) (Packet + IPHLEN);
CurSEQ = (ntohl (tcph->th_seq));
if (debug)
{
printf ("SRC:%s(%d) ", inet_ntoa (ip->ip_src), tcph->th_sport);
printf ("DST:%s(%d)\n", inet_ntoa (ip->ip_dst), tcph->th_dport);
}
if (ip->ip_src.s_addr <= 0 || ip->ip_dst.s_addr <= 0)
return;
for (i = 0; i < 10; i++)
{
if (!TCPport[i])
continue;
if (ISeq (tcph->th_sport, TCPport[i]) ||
ISeq (tcph->th_dport, TCPport[i]))
match = 1;
}
if (!match)
return;
{
register int length = ((IPLEN - (IPHLEN * 4)) - (tcph->th_off * 4));
if (debug)
printf ("Seq=%08X,pl=%04X,dl=%04X,l=%04X,iph=%04X,ipl=%04X,tf=%04X\n",
CurSEQ, pktlen,
(IPLEN - (IPHLEN * 4)), length, ip->ip_hl, ip->ip_len, tcph->th_off);
p = (u_char *) Packet;
p += ((ip->ip_hl * 4) + (tcph->th_off * 4));
if (ip->ip_src.s_addr <= 0 || ip->ip_dst.s_addr <= 0)
return;
if (translate)
{
src = translate_host (inet_ntoa (ip->ip_src));
dst = translate_host (inet_ntoa (ip->ip_dst));
} else
{
src = strdup (inet_ntoa (ip->ip_src));
dst = strdup (inet_ntoa (ip->ip_dst));
}
sprintf (sp, "%d", tcph->th_sport);
sprintf (dp, "%d", tcph->th_dport);
sv = getservbyport (tcph->th_sport, "tcp");
if (sv)
strcpy (sp, sv->s_name);
sv = getservbyport (tcph->th_dport, "tcp");
if (sv)
strcpy (dp, sv->s_name);
printf ("%s/%s %s/%s ", src, sp, dst, dp);
while (length-- > 0)
{
fputc (*p, stdout);
if (*p == '\n' || *p == '\r')
{
printf ("\n%s/%d %s/%d ", inet_ntoa (ip->ip_src), tcph->th_sport,
inet_ntoa (ip->ip_dst), tcph->th_dport);
}
p++;
fflush (stdout);
}
printf ("\n");
}
}
/*
* signal handler
*/
void
flushit ()
{
printf ("\n\n[Terminating]\n");
fflush (stdout);
exit (1);
}
/*
* opens network interface, performs ioctls and reads from it, passing data
* to filter function
*/
void
do_it ()
{
int cc;
char *buf;
u_short sp_ts_len;
if (!(buf = malloc (CHUNKSIZE)))
Pexit (1, "Eth: malloc");
/* this /dev/nit initialization code pinched from etherfind */
{
struct strioctl si;
struct ifreq ifr;
struct timeval timeout;
u_int chunksize = CHUNKSIZE;
u_long if_flags = NI_PROMISC;
if ((if_fd = open (NIT_DEV, O_RDONLY)) < 0)
Pexit (1, "Eth: nit open");
if (ioctl (if_fd, I_SRDOPT, (char *) RMSGD) < 0)
Pexit (1, "Eth: ioctl (I_SRDOPT)");
si.ic_timout = INFTIM;
if (ioctl (if_fd, I_PUSH, "nbuf") < 0)
Pexit (1, "Eth: ioctl (I_PUSH \"nbuf\")");
timeout.tv_sec = 1;
timeout.tv_usec = 0;
si.ic_cmd = NIOCSTIME;
si.ic_len = sizeof (timeout);
si.ic_dp = (char *) &timeout;
if (ioctl (if_fd, I_STR, (char *) &si) < 0)
Pexit (1, "Eth: ioctl (I_STR: NIOCSTIME)");
si.ic_cmd = NIOCSCHUNK;
si.ic_len = sizeof (chunksize);
si.ic_dp = (char *) &chunksize;
if (ioctl (if_fd, I_STR, (char *) &si) < 0)
Pexit (1, "Eth: ioctl (I_STR: NIOCSCHUNK)");
strncpy (ifr.ifr_name, device, sizeof (ifr.ifr_name));
ifr.ifr_name[sizeof (ifr.ifr_name) - 1] = '\0';
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof (ifr);
si.ic_dp = (char *) 𝔦
if (ioctl (if_fd, I_STR, (char *) &si) < 0)
Pexit (1, "Eth: ioctl (I_STR: NIOCBIND)");
si.ic_cmd = NIOCSFLAGS;
si.ic_len = sizeof (if_flags);
si.ic_dp = (char *) &if_flags;
if (ioctl (if_fd, I_STR, (char *) &si) < 0)
Pexit (1, "Eth: ioctl (I_STR: NIOCSFLAGS)");
if (ioctl (if_fd, I_FLUSH, (char *) FLUSHR) < 0)
Pexit (1, "Eth: ioctl (I_FLUSH)");
}
while ((cc = read (if_fd, buf, CHUNKSIZE)) >= 0)
{
register char *bp = buf, *bufstop = (buf + cc);
while (bp < bufstop)
{
register char *cp = bp;
register struct nit_bufhdr *hdrp;
hdrp = (struct nit_bufhdr *) cp;
cp += sizeof (struct nit_bufhdr);
bp += hdrp->nhb_totlen;
filter (cp, (u_long) hdrp->nhb_msglen);
}
}
Pexit ((-1), "Eth: read");
}
int
GetPorts (p, Tp)
char *p;
int Tp;
{
/* get portname, conver from symbolic if needed */
if ((TCPport[Tp] = atoi (p)) == 0)
{
struct servent *sv = getservbyname (p, "tcp");
if (sv)
TCPport[Tp] = sv->s_port;
else
{
printf ("Unknown port: %s\n", p);
exit (-1);
}
}
return (1);
}
void
Usage ()
{
fprintf (stderr,
"Usage: %s [-i device] [-d] port ... \n", ProgName);
fprintf (stderr, " -d Debug\n");
fprintf (stderr, " -i device Logical ethernet interface\n");
fprintf (stderr, " -t Translate IP to Hostname\n");
fprintf (stderr, " Port Port name or number\n\n");
fprintf (stderr, " Example: %s -i le0 login finger 21\n",
ProgName);
exit (1);
}
void
main (argc, argv)
int argc;
char **argv;
{
int s, ac = 1, i = 0, x = 0;
char cbuf[BUFSIZ];
struct ifconf ifc;
struct servent *sv;
ProgName = argv[0];
if (argc == 1)
Usage ();
/* parse args */
device = NULL;
while (argv[ac][0] == '-')
{
register char ch = argv[ac++][1];
switch (toupper (ch))
{
case 'I':
device = argv[ac++];
break;
case 'D':
debug = 1;
break;
case 'T':
translate = 1;
break;
default:
Usage ();
break;
}
}
while (argv[ac])
{
GetPorts (argv[ac++], i);
i++;
}
/* if not a specified device, determine it */
if (!device)
{
if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
Pexit (1, "Eth: socket");
ifc.ifc_len = sizeof (cbuf);
ifc.ifc_buf = cbuf;
if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0)
Pexit (1, "Eth: ioctl");
close (s);
device = ifc.ifc_req->ifr_name;
}
printf ("=> IP/TCP monitor\n");
printf ("=> Configured device %s [%s], %ssynching stream ...\n",
device, NIT_DEV, (debug) ? "(debug) " : "");
printf ("=> Scanning ports: ");
for (i = 0; i < 10; i++)
{
if (!TCPport[i])
continue;
sv = getservbyport (TCPport[i], "tcp");
if (sv)
printf ("%s ", sv->s_name);
else
printf ("%d ", TCPport[i]);
}
printf ("\n");
fflush (stdout);
signal (SIGINT, flushit);
signal (SIGTERM, flushit);
do_it ();
/* NOT_REACHED */
}
char *
translate_host (s)
char s[18];
{
int size = 0;
static char hostname[64];
char *h;
struct sockaddr_in sin;
struct hostent *host;
h = hostname;
bzero ((char *) &sin, sizeof (sin));
sin.sin_addr.s_addr = inet_addr (s);
if (sin.sin_addr.s_addr != -1 && sin.sin_addr.s_addr != 0)
{
sin.sin_family = AF_INET;
host = gethostbyaddr ((char *) &sin.sin_addr, sizeof (sin),
sin.sin_family);
if (host)
{
strcpy (hostname, host->h_name);
size = sizeof (hostname) - strlen (hostname);
if (!index (hostname, '.'))
{
if (!(_res.options & RES_INIT))
res_init ();
if (_res.defdname[0])
{
if (_res.defdname[strlen (_res.defdname) - 1] == '.')
_res.defdname[strlen (_res.defdname) - 1] = 0;
strncat (hostname, ".", size);
strncat (hostname, _res.defdname, size - 2);
}
}
return (h);
}
}
return (s);
}